grammar input;

options {
  output=AST;
  ASTLabelType = CommonTree;
}

tokens {
  BNFDECL;
  REDECL;
  PROD;
  GRAMMAR;
  EPSILON;
}
@header {
package compiler.antlr;
}
@lexer::header 
{
package compiler.antlr;
}

grammarSpec 
	: regularExprDecls '%' bnfDecls -> ^(GRAMMAR regularExprDecls bnfDecls)
	;

regularExprDecls
	: (REID '=' StringLiteral ';')* -> ^(REDECL REID StringLiteral)+
	;

bnfDecls: (BNFID '=' bnfProductions ';') * -> ^(BNFDECL BNFID bnfProductions)+
	;
	
bnfProductions
	: bnfProduction ('|' bnfProduction) * -> ^(PROD bnfProduction)+
	;
	
bnfProduction
	: ( BNFID | REID ) +
	| -> ^(EPSILON)
	;	

REID 	: '[' IDHEAD IDTAIL * ']' ;
BNFID	: '<' IDHEAD IDTAIL * '>' ;	

WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ 	{ $channel = HIDDEN; } ;

RECHAR : IDTAIL ;

fragment DIGIT	: '0'..'9' ;
fragment IDHEAD : 'A'..'Z'|'a'..'z'|'_' ; 			
fragment IDTAIL : 'A'..'Z'|'a'..'z'|'0'..'9'|'_'  ;

StringLiteral
	: '"' ( StrChar )+ '"' /*{setText(getText().substring(1, getText().length()-1));}*/
	;

StrChar : EscapeSeq | ~('\\' | '"')
	;

fragment
EscapeSeq: '\\|'
	   | '\\*'
	   | '\\"'
	   | '\\('
	   | '\\)'
	   | '\\\\'
   	   | '\\['
   	   | '\\]'
  	   | '\\.';

COMMENT
    :   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

LINE_COMMENT
    : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    ;
 			
